package utils;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

public class Encriptador {
	private Cipher ecipher, dcipher;
	private SecretKey llave = generarLlave();
	private String tipoLlave;
	private static Encriptador instancia;

	public static Encriptador get(){
		if (instancia == null)
			instancia = new Encriptador();
		return instancia;
	}
	
	/**
	 * Dado que la clase genera una llave aleatoria, es necesario que la misma sea static o singleton,
	 * ya que debe pasarse la instancia con la misma llave. Si creo nuevas instancias en dos lugares distintos,
	 * el algoritmo des/encriptaría con una llave distinta, dando resultados negativos. 
	 */
	private Encriptador() {
			try {
				ecipher = Cipher.getInstance(llave.getAlgorithm());
				dcipher = Cipher.getInstance(llave.getAlgorithm());
				ecipher.init(Cipher.ENCRYPT_MODE, llave);
				dcipher.init(Cipher.DECRYPT_MODE, llave);
			} catch (NoSuchPaddingException e) {
				System.out.println("EXCEPTION: NoSuchPaddingException");
			} catch (NoSuchAlgorithmException e) {
				System.out.println("EXCEPTION: NoSuchAlgorithmException");
			} catch (InvalidKeyException e) {
				System.out.println("EXCEPTION: InvalidKeyException");
			}
	}

	public String encriptar(String str) {
		try {
			byte[] utf8 = str.getBytes("UTF8");
			byte[] enc = ecipher.doFinal(utf8);

			return new sun.misc.BASE64Encoder().encode(enc);
		} catch (Exception e) {}
		return null;
	}
	
	public String desencriptar(String str) {
		try {
			byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
			byte[] utf8 = dcipher.doFinal(dec);

			return new String(utf8, "UTF8");
		} catch (Exception e) {}
		return null;
	}

	/*
	 * Genera el tipo de encriptación. Cambiar la variable String por el tipo de encriptación que deseemos.
	 */
	private SecretKey generarLlave() {
		tipoLlave = "DESede";
		try{
			return KeyGenerator.getInstance(tipoLlave).generateKey();
		}catch (Exception e) {return null;}
	}

	
	//getters & setters
	public void setTipoLlave(String tipoLlave) {
		this.tipoLlave = tipoLlave;
	}

	public String getTipoLlave() {
		return tipoLlave;
	}
}